
<!DOCTYPE html>
<html lang="zh-Hans" class="loading">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Java使用mpxj导入.mpp格式的Project文件（甘特图） - Luis Blog</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="Luis,"> 
    <meta name="description" content="java开发工程师，喜欢代码，喜欢技术,

最近换工作了，主要的项目都是企业内部为支撑的管理平台，刚入入职没多久，遇到了一个需求，就是导入微软的Project文件，踩过不少坑，所以记录一下，后续还有从数据库导出Project引导文件，也就,"> 
    <meta name="author" content="winter chen"> 
    <link rel="alternative" href="atom.xml" title="Luis Blog" type="application/atom+xml"> 
    <link rel="icon" href="/img/favicon.png"> 
    
    
<link rel="stylesheet" href="/css/diaspora.css">

	<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <script>
         (adsbygoogle = window.adsbygoogle || []).push({
              google_ad_client: "ca-pub-8691406134231910",
              enable_page_level_ads: true
         });
    </script>
    <script async custom-element="amp-auto-ads"
        src="https://cdn.ampproject.org/v0/amp-auto-ads-0.1.js">
    </script>
<meta name="generator" content="Hexo 4.2.0"></head>

<body class="loading">
    <span id="config-title" style="display:none">Luis Blog</span>
    <div id="loader"></div>
    <div id="single">
    <div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <a class="iconfont icon-home image-icon" href="javascript:;" data-url="https://blog.winterchen.com"></a>
    <div title="播放/暂停" class="iconfont icon-play"></div>
    <h3 class="subtitle">Java使用mpxj导入.mpp格式的Project文件（甘特图）</h3>
    <div class="social">
        <div>
            <div class="share">
                <a title="获取二维码" class="iconfont icon-scan" href="javascript:;"></a>
            </div>
            <div id="qr"></div>
        </div>
    </div>
    <div class="scrollbar"></div>
</div>

    <div class="section">
        <div class="article">
    <div class='main'>
        <h1 class="title">Java使用mpxj导入.mpp格式的Project文件（甘特图）</h1>
        <div class="stuff">
            <span>一月 18, 2018</span>
            
  <ul class="post-tags-list" itemprop="keywords"><li class="post-tags-list-item"><a class="post-tags-list-link" href="/tags/java/" rel="tag">java</a></li></ul>


        </div>
        <div class="content markdown">
            <p><img src="http://img.winterchen.com/martin-shreder-349256-unsplash.jpg" alt=""></p>
<blockquote>
<p>最近换工作了，主要的项目都是企业内部为支撑的管理平台，刚入入职没多久，遇到了一个需求，就是导入微软的Project文件，踩过不少坑，所以记录一下，后续还有从数据库导出Project引导文件，也就是xml文件</p>
</blockquote>
<a id="more"></a>

<p><img src="http://img.blog.csdn.net/20180117180051197?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvV2ludGVyX2NoZW4wMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h2 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 读取project文件 --&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">	&lt;groupId&gt;net.sf.mpxj&lt;&#x2F;groupId&gt;</span><br><span class="line">	&lt;artifactId&gt;mpxj&lt;&#x2F;artifactId&gt;</span><br><span class="line">	&lt;version&gt;7.1.0&lt;&#x2F;version&gt;</span><br><span class="line">&lt;&#x2F;dependency&gt;</span><br></pre></td></tr></table></figure>
<h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p> 博主使用的读取方式是递归读取的，无论Project文件中的任务有多少层，都可以读到，好了，直接看代码，注意看注释：</p>
<h3 id="核心方法"><a href="#核心方法" class="headerlink" title="核心方法"></a>核心方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line">   <span class="meta">@Override</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">readMmpFileToDB</span><span class="params">(File file)</span> </span>&#123;<span class="comment">//如果读取的是MultipartFile，那么直接使用获取InputStream即可</span></span><br><span class="line">       <span class="keyword">try</span>&#123;</span><br><span class="line">       	<span class="comment">//这个是读取文件的组件</span></span><br><span class="line">           MPPReader mppRead = <span class="keyword">new</span> MPPReader();</span><br><span class="line">           <span class="comment">//注意，如果在这一步出现了读取异常，肯定是版本不兼容，换个版本试试</span></span><br><span class="line">           ProjectFile pf = mppRead.read(file);</span><br><span class="line">           <span class="comment">//从文件中获取的任务对象</span></span><br><span class="line">           List&lt;Task&gt; tasks = pf.getChildTasks();</span><br><span class="line">           <span class="comment">//这个可以不用，这个list只是我用来装下所有的数据，如果不需要可以不使用</span></span><br><span class="line">           List&lt;Project&gt; proList = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">           <span class="comment">//这个是用来封装任务的对象，为了便于区别，初始化批次号，然后所有读取的数据都需要加上批次号</span></span><br><span class="line">           Project pro = <span class="keyword">new</span> Project();</span><br><span class="line">           pro.setBatchNum(StringUtils.UUID());<span class="comment">//生成批次号UUID</span></span><br><span class="line">           <span class="comment">//这个方法是一个递归方法</span></span><br><span class="line">           getChildrenTask(tasks.get(<span class="number">0</span>), pro ,proList, <span class="number">0</span>);</span><br><span class="line">       &#125;<span class="keyword">catch</span> (MPXJException e) &#123;</span><br><span class="line">           logger.error(e.getMessage());</span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">       &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">           logger.error(e.getMessage());</span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 这个方法是一个递归</span></span><br><span class="line"><span class="comment"> * 方法的原理：进行读取父任务，如果下一层任务还是父任务，那么继续调用当前方法，如果到了最后一层，调用另外一个读取底层的方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> task</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> project</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> list</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> levelNum</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">getChildrenTask</span><span class="params">(Task task, Project project, List&lt;Project&gt; list, <span class="keyword">int</span> levelNum)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(task.getResourceAssignments().size() == <span class="number">0</span>)&#123;<span class="comment">//这个判断是进行是否是最后一层任务的判断==0说明是父任务</span></span><br><span class="line">            levelNum ++;<span class="comment">//层级号需要增加，这个只是博主用来记录该层的层级数</span></span><br><span class="line">            List&lt;Task&gt; tasks = task.getChildTasks();<span class="comment">//继续获取子任务</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; tasks.size(); i++) &#123;<span class="comment">//该循环是遍历所有的子任务</span></span><br><span class="line">                <span class="keyword">if</span>(tasks.get(i).getResourceAssignments().size() == <span class="number">0</span>)&#123;<span class="comment">//说明还是在父任务层</span></span><br><span class="line">                    Project pro = <span class="keyword">new</span> Project();</span><br><span class="line">                    <span class="keyword">if</span> (project.getProjId() != <span class="keyword">null</span>)&#123;<span class="comment">//说明不是第一次读取了，因为如果是第一层，那么还没有进行数据库的添加，没有返回主键Id</span></span><br><span class="line">                        pro.setParentId(project.getProjId());<span class="comment">//将上一级目录的Id赋值给下一级的ParentId</span></span><br><span class="line">                    &#125;</span><br><span class="line">                    pro.setBatchNum(project.getBatchNum());<span class="comment">//批量号</span></span><br><span class="line">                    pro.setImportTime(<span class="keyword">new</span> Date());<span class="comment">//导入时间</span></span><br><span class="line">                    pro.setLevel(levelNum);<span class="comment">//层级</span></span><br><span class="line">                    pro.setTaskName(tasks.get(i).getName());<span class="comment">//这个是获取文件中的“任务名称”列的数据</span></span><br><span class="line">                    pro.setDurationDate(tasks.get(i).getDuration().toString());<span class="comment">//获取的是文件中的“工期”</span></span><br><span class="line">                    pro.setStartDate(tasks.get(i).getStart());<span class="comment">//获取文件中的 “开始时间”</span></span><br><span class="line">                    pro.setEndDate(tasks.get(i).getFinish());<span class="comment">//获取文件中的 “完成时间”</span></span><br><span class="line">                    pro.setResource(tasks.get(i).getResourceGroup());<span class="comment">//获取文件中的 “资源名称”</span></span><br><span class="line">                    <span class="keyword">this</span>.addProjectInfo(pro);<span class="comment">//将该条数据添加到数据库，并且会返回主键Id，用做子任务的ParentId,这个需要在mybatis的Mapper中设置</span></span><br><span class="line">                    getChildrenTask(tasks.get(i), pro,list,levelNum);<span class="comment">//继续进行递归，当前保存的只是父任务的信息</span></span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;<span class="comment">//继续进行递归</span></span><br><span class="line">                    getChildrenTask(tasks.get(i), project, list, levelNum);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;<span class="comment">//说明已经到了最底层的子任务了，那么就调用进行最底层数据读取的方法</span></span><br><span class="line">            <span class="keyword">if</span> (project.getProjId() != <span class="keyword">null</span>)&#123;</span><br><span class="line">                getResourceAssignment(task, project, list, levelNum);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">getResourceAssignment</span><span class="params">(Task task, Project project, List&lt;Project&gt; proList, <span class="keyword">int</span> levelNum)</span></span>&#123;</span><br><span class="line">    List&lt;ResourceAssignment&gt; list = task.getResourceAssignments();<span class="comment">//读取最底层的属性</span></span><br><span class="line">    ResourceAssignment rs = list.get(<span class="number">0</span>);</span><br><span class="line">    Project pro = <span class="keyword">new</span> Project();</span><br><span class="line">    pro.setTaskName(task.getName());</span><br><span class="line">    pro.setParentId(project.getProjId());</span><br><span class="line">    pro.setLevel(levelNum);</span><br><span class="line">    pro.setImportTime(<span class="keyword">new</span> Date());</span><br><span class="line">    pro.setBatchNum(project.getBatchNum());</span><br><span class="line">    pro.setDurationDate(task.getDuration().toString());</span><br><span class="line">    pro.setStartDate(rs.getStart());<span class="comment">//注意，这个从ResourceAssignment中读取</span></span><br><span class="line">    pro.setEndDate(rs.getFinish());<span class="comment">//同上</span></span><br><span class="line">    String resource = <span class="string">""</span>;</span><br><span class="line">    <span class="keyword">if</span>(list.size() &gt; <span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; list.size(); i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (list.get(i).getResource() != <span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">if</span>(i &lt; list.size() - <span class="number">1</span>)&#123;</span><br><span class="line">                    resource += list.get(i).getResource().getName() + <span class="string">","</span>;</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    resource += list.get(i).getResource().getName();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(list.size() &gt; <span class="number">0</span> &amp;&amp; list.get(<span class="number">0</span>).getResource() != <span class="keyword">null</span>)&#123;</span><br><span class="line">            resource = list.get(<span class="number">0</span>).getResource().getName();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(!StringUtils.isEmpty(resource))&#123;</span><br><span class="line">        pro.setResource(resource);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.addProjectInfo(pro);<span class="comment">//将数据保存在数据库中,同样会返回主键</span></span><br><span class="line">    proList.add(pro);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h3 id="封装对象"><a href="#封装对象" class="headerlink" title="封装对象"></a>封装对象</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.winter.model;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Project文件封装类</span></span><br><span class="line"><span class="comment"> * Created By Donghua.Chen on  2018/1/9</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Project</span> </span>&#123;</span><br><span class="line">    <span class="comment">/* 自增主键Id */</span></span><br><span class="line">    <span class="keyword">private</span> Integer projId;</span><br><span class="line">    <span class="comment">/* 上级Id */</span></span><br><span class="line">    <span class="keyword">private</span> Integer parentId;</span><br><span class="line">    <span class="comment">/* 结构层级 */</span></span><br><span class="line">    <span class="keyword">private</span> Integer level;</span><br><span class="line">    <span class="comment">/* 任务名称 */</span></span><br><span class="line">    <span class="keyword">private</span> String taskName;</span><br><span class="line">    <span class="comment">/* 工期 */</span></span><br><span class="line">    <span class="keyword">private</span> String durationDate;</span><br><span class="line">    <span class="comment">/* 开始时间 */</span></span><br><span class="line">    <span class="keyword">private</span> Date startDate;</span><br><span class="line">    <span class="comment">/* 结束时间 */</span></span><br><span class="line">    <span class="keyword">private</span> Date endDate;</span><br><span class="line">    <span class="comment">/* 前置任务ID */</span></span><br><span class="line">    <span class="keyword">private</span> Integer preTask;</span><br><span class="line">    <span class="comment">/* 资源名称 */</span></span><br><span class="line">    <span class="keyword">private</span> String resource;</span><br><span class="line">    <span class="comment">/* 导入时间 */</span></span><br><span class="line">    <span class="keyword">private</span> Date importTime;</span><br><span class="line">    <span class="comment">/* 批次号 */</span></span><br><span class="line">    <span class="keyword">private</span> String batchNum;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//省略get、set方法</span></span><br></pre></td></tr></table></figure>

<h3 id="Mybatis-接口方法"><a href="#Mybatis-接口方法" class="headerlink" title="Mybatis 接口方法"></a>Mybatis 接口方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 插入project数据</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> project</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">addProjectSelective</span><span class="params">(Project project)</span></span>;</span><br></pre></td></tr></table></figure>

<h3 id="Mapper"><a href="#Mapper" class="headerlink" title="Mapper"></a>Mapper</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">"TABLE_PROJECT"</span>&gt;</span></span><br><span class="line">  PROJECT</span><br><span class="line"><span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 插入数据之后返回主键 需要这两个配置： useGeneratedKeys="true" keyProperty="projId" --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">"addProjectSelective"</span> <span class="attr">useGeneratedKeys</span>=<span class="string">"true"</span> <span class="attr">keyProperty</span>=<span class="string">"projId"</span> <span class="attr">parameterType</span>=<span class="string">"com.winter.model.Project"</span>&gt;</span></span><br><span class="line">    INSERT INTO</span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"TABLE_PROJECT"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">trim</span> <span class="attr">prefix</span>=<span class="string">"("</span> <span class="attr">suffix</span>=<span class="string">")"</span> <span class="attr">suffixOverrides</span>=<span class="string">","</span> &gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"parentId != null"</span>&gt;</span></span><br><span class="line">            parentId,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"level != null"</span>&gt;</span></span><br><span class="line">            level,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"taskName != null"</span>&gt;</span></span><br><span class="line">            taskName,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"durationDate != null"</span>&gt;</span></span><br><span class="line">            durationDate,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"startDate != null"</span>&gt;</span></span><br><span class="line">            startDate,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"endDate != null"</span>&gt;</span></span><br><span class="line">            endDate,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"preTask != null"</span>&gt;</span></span><br><span class="line">            preTask,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"resource != null"</span>&gt;</span></span><br><span class="line">            resource,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"importTime != null"</span>&gt;</span></span><br><span class="line">            importTime,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"importTime != null"</span>&gt;</span></span><br><span class="line">            batchNum,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">trim</span> <span class="attr">prefix</span>=<span class="string">"values ("</span> <span class="attr">suffix</span>=<span class="string">")"</span> <span class="attr">suffixOverrides</span>=<span class="string">","</span> &gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"parentId != null"</span>&gt;</span></span><br><span class="line">            #&#123;parentId, jdbcType=INTEGER&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"level != null"</span>&gt;</span></span><br><span class="line">            #&#123;level, jdbcType=INTEGER&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"taskName != null"</span>&gt;</span></span><br><span class="line">            #&#123;taskName, jdbcType=VARCHAR&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"durationDate != null"</span>&gt;</span></span><br><span class="line">            #&#123;durationDate, jdbcType=VARCHAR&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"startDate != null"</span>&gt;</span></span><br><span class="line">            #&#123;startDate, jdbcType=DATE&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"endDate != null"</span>&gt;</span></span><br><span class="line">            #&#123;endDate, jdbcType=DATE&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"preTask != null"</span>&gt;</span></span><br><span class="line">            #&#123;preTask, jdbcType=INTEGER&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"resource != null"</span>&gt;</span></span><br><span class="line">            #&#123;resource, jdbcType=VARCHAR&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"importTime != null"</span>&gt;</span></span><br><span class="line">            #&#123;importTime, jdbcType=DATE&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"batchNum != null"</span>&gt;</span></span><br><span class="line">            #&#123;batchNum, jdbcType=VARCHAR&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h2><p><img src="http://img.blog.csdn.net/20180117180307631?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvV2ludGVyX2NoZW4wMDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h2 id="拓展"><a href="#拓展" class="headerlink" title="拓展"></a>拓展</h2><p>当然，还有很多自定义的字段读取，如果有需要可以联系我，或者看官方文档<br>email：<a href="mailto:1085143002@qq.com">1085143002@qq.com</a></p>
<h2 id="相关资源"><a href="#相关资源" class="headerlink" title="相关资源"></a>相关资源</h2><ul>
<li>mpxj官方API文档：<a href="http://www.mpxj.org/apidocs/index.html" target="_blank" rel="noopener">http://www.mpxj.org/apidocs/index.html</a></li>
<li>项目源码：<a href="https://github.com/WinterChenS/springboot-mybatis-demo" target="_blank" rel="noopener">https://github.com/WinterChenS/springboot-mybatis-demo</a></li>
<li>导入模板在源码的file文件夹中，sql在sql文件夹中</li>
</ul>

            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls" data-autoplay="false">
                <source type="audio/mpeg" src="">
            </audio>
            
                <ul id="audio-list" style="display:none">
                    
                        
                            <li title='0' data-url='https://raw.githubusercontent.com/WinterChenS/imgrpo/master/mp3/%E6%96%B0%E8%A3%A4%E5%AD%90-%E7%94%9F%E6%B4%BB%E5%9B%A0%E4%BD%A0%E8%80%8C%E7%81%AB%E7%83%AD.mp3'></li>
                        
                    
                </ul>
            
        </div>
        
    <div id='gitalk-container' class="comment link"
		data-enable='false'
        data-ae='false'
        data-ci='77f2adc33e0112d086d7'
        data-cs='e926aa3a621556609b2c2b76d89320fa524e23cd'
        data-r='WinterChenS.github.io'
        data-o='WinterChenS'
        data-a='WinterChenS'
        data-d='false'
    >查看评论</div>


    </div>
    
</div>


    </div>
</div>
</body>


<script src="//lib.baomitu.com/jquery/1.8.3/jquery.min.js"></script>
<script src="/js/plugin.js"></script>
<script src="/js/typed.js"></script>
<script src="/js/diaspora.js"></script>


<link rel="stylesheet" href="/photoswipe/photoswipe.css">
<link rel="stylesheet" href="/photoswipe/default-skin/default-skin.css">


<script src="/photoswipe/photoswipe.min.js"></script>
<script src="/photoswipe/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>





<!-- Google Analytics -->
<script type="text/javascript">
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'G-30C04D6TMS', 'auto');
  ga('send', 'pageview');
</script>
<!-- End Google Analytics -->


</html>
